<template>
  <div class="fx-switch" :class="{disabled}" @click="switchClick">
    <div class="out-left-text" v-if="!inside&&($slots.close||closeText!=='')" :style="textStyle('close')">
      <slot name="close">{{ closeText }}</slot>
    </div>
    <div class="switch-wrapper" :style="switchStyle">
      <div class="inside-left-text" v-if="inside" :style="textStyle('close')">
        {{ closeText.trim().charAt(0) }}
      </div>
      <div class="dot" :class="[modelValue?'open':'close']">
        <span v-if="loading"></span>
        <span v-if="loading"></span>
      </div>
      <div class="inside-right-text" v-if="inside" :style="textStyle('open')">
        {{ openText.trim().charAt(0) }}
      </div>
    </div>
    <div class="out-right-text" v-if="!inside&&($slots.open||openText!=='')" :style="textStyle('open')">
      <slot name="open">{{ openText }}</slot>
    </div>
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, ref } from 'vue'
import { useModelWatch } from '@/base/hooks'
import { colorRgb } from '@/base/utils'

type BeforeChange = (cb: () => void) => void

interface SwitchProps {
  modelValue: boolean;
  closeText: string;
  openText: string;
  closeColor: string;
  openColor: string;
  disabled: boolean;
  inside: boolean;
  loading: boolean;
  beforeChange: BeforeChange;
}

export default defineComponent({
  name: 'FSwitch',
  props: {
    modelValue: {
      type: Boolean as PropType<boolean>,
      default: false,
      required: true
    },
    // 关闭文字
    closeText: {
      type: String as PropType<string>,
      default: ''
    },
    // 开启文字
    openText: {
      type: String as PropType<string>,
      default: ''
    },
    // 关闭颜色
    closeColor: {
      type: String as PropType<string>,
      default: 'rgb(219,213,213)'
    },
    // 开启颜色
    openColor: {
      type: String as PropType<string>,
      default: 'rgb(45, 183, 245)'
    },
    // 禁用
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 是否内嵌文字
    inside: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 加载中
    loading: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    // 切换前
    beforeChange: {
      type: Function as PropType<BeforeChange>,
      default: null
    }
  },
  emits: ['update:modelValue', 'change'],
  setup (props: SwitchProps) {
    // 当前状态
    const switchValue = ref<boolean>(props.modelValue)
    // 数据双向绑定hook
    useModelWatch<boolean>(() => props.modelValue, switchValue)

    // 样式处理
    const switchStyle = computed<{ backgroundColor: string }>(() => {
      const closeColor = props.disabled ? colorRgb(props.closeColor, 0.3) : props.closeColor
      const openColor = props.disabled ? colorRgb(props.openColor, 0.3) : props.openColor
      return {
        backgroundColor: switchValue.value ? openColor : closeColor
      }
    })

    // 点击事件
    const switchClick = (): void => {
      if (props.disabled || props.loading) return
      if (props.beforeChange) {
        props.beforeChange(() => {
          switchValue.value = !switchValue.value
        })
        return
      }
      switchValue.value = !switchValue.value
    }

    // 文字颜色
    const textStyle = (status: 'open' | 'close'): { color: string | null } => {
      const closeColor = props.disabled ? colorRgb(props.closeColor, 0.3) : props.closeColor
      const openColor = props.disabled ? colorRgb(props.openColor, 0.3) : props.openColor
      if (props.inside) return { color: status === 'open' ? openColor : closeColor }
      if (status === 'open' && switchValue.value) return { color: openColor }
      if (status === 'close' && !switchValue.value) return { color: closeColor }
      return { color: props.disabled ? '#C0C4CC' : null }
    }

    return {
      switchValue,
      switchStyle,
      switchClick,
      textStyle
    }
  }
})
</script>
